package com.team.employment.web.admin.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.team.employment.common.exception.CustomException;
import com.team.employment.common.result.ResultCodeEnum;
import com.team.employment.model.entity.UserInfo;
import com.team.employment.model.enums.BaseStatus;
import com.team.employment.model.enums.UserType;
import com.team.employment.web.admin.custom.utils.JwtUtil;
import com.team.employment.web.admin.custom.utils.PasswordUtil;
import com.team.employment.web.admin.custom.utils.SmsUtil;
import com.team.employment.web.admin.dto.UserQueryDto;
import com.team.employment.web.admin.mapper.ResumeInfoMapper;
import com.team.employment.web.admin.mapper.UserInfoMapper;
import com.team.employment.web.admin.service.UserInfoService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
* @author jade
* @description 针对表【user_info(用户信息表)】的数据库操作Service实现
* @createDate 2025-04-11 15:49:27
*/
@Service
@RequiredArgsConstructor
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
    implements UserInfoService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private ResumeInfoMapper resumeInfoMapper;

    private final RedisTemplate<String, Object> redisTemplate;
    private final JwtUtil jwtUtil;
    private final SmsUtil smsUtil;
    //用户登录
    @Override
    public UserInfo login(String phone, String password) {
        //查询数据库确认用户是否存在
        UserInfo userInfo = lambdaQuery()
                .eq(UserInfo::getPhone, phone)
                .select(
                        UserInfo::getPassword,
                        UserInfo::getSalt,
                        UserInfo::getStatus,
                        UserInfo::getPhone,
                        UserInfo::getUsername,
                        UserInfo::getAvatarUrl
                )
                .one();
        if (userInfo == null) {
            throw new CustomException(ResultCodeEnum.ADMIN_ACCOUNT_NOT_EXIST_ERROR);
        }
        //验证密码是否正确
        if (!PasswordUtil.verifyPassword(password, userInfo.getSalt(), userInfo.getPassword())) {
            //密码错误
            throw new CustomException(ResultCodeEnum.ADMIN_ACCOUNT_ERROR);
        }
        //检查用户状态（是否被禁用）
        if (userInfo.getStatus() != BaseStatus.ENABLE) {
            throw new CustomException(ResultCodeEnum.APP_ACCOUNT_DISABLED_ERROR);//账号已被禁用
        }
        //生成JWT并返回给用户，同时将token存储到Redis中，设置失效时间为30分钟
        String token = jwtUtil.generateToken(phone);
        userInfo.setToken(token);
        userInfo.setPassword(null); // 不返回密码

        // 存储token到redis，实现单点登录
        redisTemplate.opsForValue().set("user:token:" + phone, token, 30, TimeUnit.MINUTES);
        return userInfo; // 登录成功，返回用户信息
    }


    //用户注册
    @Override
    public void register(UserInfo userInfo) {
        if (lambdaQuery().eq(UserInfo::getPhone, userInfo.getPhone()).count() > 0) {
            throw new CustomException(ResultCodeEnum.ADMIN_ACCOUNT_EXIST_ERROR);//手机号已注册
        }
        // 生成盐值并加密密码
        String salt = PasswordUtil.generateSalt();
        String encryptedPassword = PasswordUtil.encryptPassword(userInfo.getPassword(), salt);

        userInfo.setPassword(encryptedPassword);
        userInfo.setSalt(salt);
        userInfo.setStatus(BaseStatus.ENABLE);
        save(userInfo);
    }
    //根据条件模糊分页查询用户列表
    @Override
    public IPage<UserInfo> pageQueryInfo(IPage<UserInfo> page, UserQueryDto userQueryDto) {
        IPage<UserInfo> list = userInfoMapper.pageQueryInfo(page,userQueryDto);
        return list;
    }
    @Override
    public void removeUserAndRelatedResume(Long id){
        //删除与用户关联的简历信息
        resumeInfoMapper.deleteByUserId(id);
        //删除用户本身
        userInfoMapper.deleteById(id);
    }
    //发送验证码
    @Override
    public String sendSmsCode(String phone){
        // 生成4位随机验证码
        String captcha = RandomUtil.randomNumbers(4);
        // 发送短信
        boolean success = smsUtil.sendSmsCode(phone, captcha);
        // 存储验证码到redis，5分钟有效
        redisTemplate.opsForValue().set("sms:code:" + phone, captcha, 5, TimeUnit.MINUTES);
        return captcha;
    }
    //找回密码
    @Override
    public String resetPassword(String phone, String captcha,String newPassword) {
        // 验证验证码
        String cacheCode = (String) redisTemplate.opsForValue().get("sms:code:" + phone);
        if (cacheCode == null || !cacheCode.equals(captcha)) {
            throw new CustomException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_ERROR);
        }

        // 查询用户
        UserInfo userInfo = lambdaQuery().eq(UserInfo::getPhone, phone).one();
        if (userInfo == null) {
            throw new CustomException(ResultCodeEnum.ADMIN_ACCOUNT_NOT_EXIST_ERROR);
        }
        // 更新密码
        String encryptedPassword = PasswordUtil.encryptPassword(newPassword, userInfo.getSalt());
        if (lambdaUpdate()
                .eq(UserInfo::getPhone, phone)
                .set(UserInfo::getPassword, encryptedPassword)
                .update()) {
            // 删除验证码
            redisTemplate.delete("sms:code:" + phone);
            // 使旧token失效
            redisTemplate.delete("user:token:" + phone);
        }
        return cacheCode;
    }

    @Override
    public UserInfo getCurrentUser() {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        System.out.println("Authentication: " + authentication);
        System.out.println("Authorities: " + authentication.getAuthorities());
        //检查认证是否有效
        if (authentication == null || !authentication.isAuthenticated()
        || authentication instanceof AnonymousAuthenticationToken){
            throw new CustomException(ResultCodeEnum.APP_LOGIN_AUTH);//未登录
        }
        //从认证信息中获取用户名
        String username = authentication.getName();
        UserInfo user = lambdaQuery()
                .eq(UserInfo::getUsername,username)
                .one();
        if (user == null){
            throw new CustomException(ResultCodeEnum.ADMIN_ACCOUNT_NOT_EXIST_ERROR);//用户不存在
        }
        System.out.println("Current User Type:"+user.getType());
        if (!UserType.ENTREPRENEURS.getCode().equals(user.getType())){
            throw new CustomException(ResultCodeEnum.ADMIN_ACCESS_FORBIDDEN);
        }
        return user;
    }
}


